package com.ywu.sentinel.sdk.service;

import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.ywu.common.result.CommonResult;
import com.ywu.sentinel.sdk.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName FlowRuleService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2025/4/14 16:47
 * @Version 1.0
 **/
@Service
@Slf4j
public class FlowRuleService {

    private final static ReentrantLock flowRuleLock = new ReentrantLock();

    private final static ReentrantLock blowRuleLock = new ReentrantLock();

    private final static ReentrantLock hotRuleLock = new ReentrantLock();

    private final static ReentrantLock systemRuleLock = new ReentrantLock();

    /**
    * @Author GroundDemo
    * @Description 加载流控规则
    * @Date 0:15 2025/4/15
    * @Param [ruleDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> flowRuleCreate(YwuFlowRuleDto ruleDto) {
        loadFlowRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 删除规则
     * @Date 8:47 2025/4/15
     * @Param [flowRuleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> flowRuleDelete(YwuFlowRuleDto flowRuleDto) {
        deleteFlowRules(flowRuleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 加载熔断规则
     * @Date 9:25 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> blowRuleCreate(YwuBlowRuleDto ruleDto) {
        loadDegradeRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 删除熔断规则
     * @Date 9:25 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> blowRuleDelete(YwuBlowRuleDto ruleDto) {
        deleteBlowRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 加载热点规则
     * @Date 9:28 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> hotRuleCreate(YwuHotRuleDto ruleDto) {
        loadHotRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 删除热点规则
     * @Date 9:28 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> hotRuleDelete(YwuHotRuleDto ruleDto) {
        deleteHotRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 加载系统规则
     * @Date 9:30 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> systemRuleCreate(YwuSystemRuleDto ruleDto) {
        loadSystemRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 删除系统规则
     * @Date 9:30 2025/4/15
     * @Param [ruleDto]
     * @return com.ywu.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> systemRuleDelete(YwuSystemRuleDto ruleDto) {
        deleteSystemRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除流控规则
    * @Date 8:48 2025/4/15
    * @Param [ruleDto]
    * @return void
    **/
    private static void deleteFlowRules(YwuFlowRuleDto ruleDto) {
        flowRuleLock.lock();
        try {
            List<FlowRule> rules = FlowRuleManager.getRules();
            List<FlowRule> newRules = new ArrayList<>();
            for (FlowRule rule : rules) {
                YwuFLowRule ywuRule = (YwuFLowRule) rule;
                if (!ruleDto.getId().equals(ywuRule.getId())) {
                    newRules.add(rule);
                }
            }
            FlowRuleManager.loadRules(newRules);
        } finally {
            flowRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 删除熔断规则
    * @Date 9:26 2025/4/15
    * @Param [ruleDto]
    * @return void
    **/
    private static void deleteBlowRules(YwuBlowRuleDto ruleDto) {
        blowRuleLock.lock();
        try {
            List<DegradeRule> rules = DegradeRuleManager.getRules();
            List<DegradeRule> newRules = new ArrayList<>();
            for (DegradeRule rule : rules) {
                YwuDegradeRule ywuRule = (YwuDegradeRule) rule;
                if (!ruleDto.getId().equals(ywuRule.getId())) {
                    newRules.add(rule);
                }
            }
            DegradeRuleManager.loadRules(newRules);
        } finally {
            blowRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 删除热点规则
    * @Date 9:29 2025/4/15
    * @Param [ruleDto]
    * @return void
    **/
    private static void deleteHotRules(YwuHotRuleDto ruleDto) {
        hotRuleLock.lock();
        try {
            List<ParamFlowRule> rules = ParamFlowRuleManager.getRules();
            List<ParamFlowRule> newRules = new ArrayList<>();
            for (ParamFlowRule rule : rules) {
                YwuParamFlowRule ywuRule = (YwuParamFlowRule) rule;
                if (!ruleDto.getId().equals(ywuRule.getId())) {
                    newRules.add(rule);
                }
            }
            ParamFlowRuleManager.loadRules(newRules);
        } finally {
            hotRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 删除系统规则
    * @Date 9:31 2025/4/15
    * @Param [ruleDto]
    * @return void
    **/
    private static void deleteSystemRules(YwuSystemRuleDto ruleDto) {
        systemRuleLock.lock();
        try {
            List<SystemRule> rules = SystemRuleManager.getRules();
            List<SystemRule> newRules = new ArrayList<>();
            for (SystemRule rule : rules) {
                // 遍历当前的所有规则，如果当前规则类型和当前传入的规则类型一致，则跳过
                switch (ruleDto.getType()) {
                    case YwuSystemRuleDto.SYSTEM_RT:
                        if (rule.getAvgRt() > 0) {
                            continue;
                        } else {
                            newRules.add(rule);
                        }
                        break;
                    case YwuSystemRuleDto.SYSTEM_LOAD:
                        if (rule.getHighestSystemLoad() > 0) {
                            continue;
                        } else {
                            newRules.add(rule);
                        }
                        break;
                    case YwuSystemRuleDto.SYSTEM_MAX_THREAD:
                        if (rule.getMaxThread() > 0) {
                            continue;
                        } else {
                            newRules.add(rule);
                        }
                        break;
                    case YwuSystemRuleDto.SYSTEM_QPS:
                        if (rule.getQps() > 0) {
                            continue;
                        } else {
                            newRules.add(rule);
                        }
                        break;
                    case YwuSystemRuleDto.SYSTEM_CPU:
                        if (rule.getHighestCpuUsage() > 0) {
                            continue;
                        } else {
                            newRules.add(rule);
                        }
                        break;
                }
            }
            SystemRuleManager.loadRules(newRules);
        } finally {
            systemRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 当前微服务加载流控规则
    * @Date 17:37 2025/4/14
    * @Param [ruleDto]
    * @return void
    **/
    public static void loadFlowRules(YwuFlowRuleDto ruleDto) {
        YwuFLowRule rule = new YwuFLowRule();
        rule.setControlBehavior(ruleDto.getControlBehavior());
        rule.setResource(ruleDto.getResource());
        rule.setCount(ruleDto.getCount());
        rule.setGrade(ruleDto.getGrade());
        rule.setStrategy(ruleDto.getStrategy());
        if (ruleDto.getControlBehavior() == 1) {
            rule.setWarmUpPeriodSec(ruleDto.getWarmUpPeriodSec());
        } else if (ruleDto.getControlBehavior() == 2) {
            rule.setMaxQueueingTimeMs(ruleDto.getMaxQueueingTimeMs());
        }
        if (ruleDto.getStrategy() == 1 || ruleDto.getStrategy() == 2) {
            rule.setRefResource(ruleDto.getRefResource());
        }
        rule.setId(ruleDto.getId());
        String limitApp = "default";
        rule.setLimitApp(limitApp);
        flowRuleLock.lock();
        try {
            List<FlowRule> rules = FlowRuleManager.getRules();
            rules.add(rule);
            // 加载流控规则
            FlowRuleManager.loadRules(rules);
        } finally {
            flowRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 当前微服务加载熔断规则
    * @Date 17:38 2025/4/14
    * @Param [ruleDto]
    * @return void
    **/
    public static void loadDegradeRules(YwuBlowRuleDto ruleDto) {
        YwuDegradeRule rule = new YwuDegradeRule();
        rule.setResource(ruleDto.getResource());
        rule.setGrade(ruleDto.getGrade());
        rule.setTimeWindow(ruleDto.getTimeWindow());
        rule.setMinRequestAmount(ruleDto.getMinRequestAmount());
        rule.setStatIntervalMs(ruleDto.getStatIntervalMs());
        String limitApp = "default";
        rule.setLimitApp(limitApp);
        if (ruleDto.getGrade() == 0) {
            rule.setCount(ruleDto.getCount());
            rule.setSlowRatioThreshold(ruleDto.getSlowRatioThreshold());
        } else if (ruleDto.getGrade() == 1) {
            rule.setCount(ruleDto.getCount());
        } else if (ruleDto.getGrade() == 2) {
            rule.setCount(ruleDto.getCount());
            rule.setSlowRatioThreshold(1);
        }
        rule.setId(ruleDto.getId());
        blowRuleLock.lock();
        try {
            List<DegradeRule> rules = DegradeRuleManager.getRules();
            rules.add(rule);
            // 加载熔断规则
            DegradeRuleManager.loadRules(rules);
        } finally {
            blowRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 本地服务加载热点规则
    * @Date 17:44 2025/4/14
    * @Param [ruleDto]
    * @return void
    **/
    public static void loadHotRules(YwuHotRuleDto ruleDto) {
        // 定义热点规则列表
        YwuParamFlowRule rule = new YwuParamFlowRule();
        rule.setResource(ruleDto.getResource());
        rule.setParamIdx(ruleDto.getParamIdx());
        rule.setCount(ruleDto.getCount());
        rule.setDurationInSec(ruleDto.getDurationInSec());
        String limitApp = "default";
        rule.setId(ruleDto.getId());
        rule.setLimitApp(limitApp);
        List<ParamFlowItem> paramFlowItems = new ArrayList<>();
        for (YwuParamItemDto dto : ruleDto.getParamFlowItemList()) {
            ParamFlowItem item = new ParamFlowItem();
            item.setObject(dto.getObject());
            item.setCount(dto.getCount());
            item.setClassType(dto.getClassType());
            paramFlowItems.add(item);
        }
        rule.setParamFlowItemList(paramFlowItems);
        hotRuleLock.lock();
        try {
            List<ParamFlowRule> rules = ParamFlowRuleManager.getRules();
            // 将规则添加到规则列表中
            rules.add(rule);
            // 加载热点规则
            ParamFlowRuleManager.loadRules(rules);
        } finally {
            hotRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 本地服务加载系统规则
    * @Date 17:46 2025/4/14
    * @Param [ruleDto]
    * @return void
    **/
    public static void loadSystemRules(YwuSystemRuleDto ruleDto) {
        // 创建一个系统规则对象
        SystemRule rule = new SystemRule();
        switch (ruleDto.getType()) {
            case YwuSystemRuleDto.SYSTEM_RT:
                rule.setAvgRt(ruleDto.getAvgRt());
                break;
            case YwuSystemRuleDto.SYSTEM_LOAD:
                rule.setHighestSystemLoad(ruleDto.getHighestSystemLoad());
                break;
            case YwuSystemRuleDto.SYSTEM_MAX_THREAD:
                rule.setMaxThread(ruleDto.getMaxThread());
                break;
            case YwuSystemRuleDto.SYSTEM_QPS:
                rule.setQps(ruleDto.getQps());
                break;
            case YwuSystemRuleDto.SYSTEM_CPU:
                rule.setHighestCpuUsage(ruleDto.getHighestCpuUsage());
                break;
        }
        systemRuleLock.lock();
        try {
            List<SystemRule> rules = SystemRuleManager.getRules();
            // 将规则添加到规则列表中
            rules.add(rule);
            // 加载系统规则
            SystemRuleManager.loadRules(rules);
        } finally {
            systemRuleLock.unlock();
        }
    }

    /**
    * @Author GroundDemo
    * @Description 查询当前微服务所有的规则信息
    * @Date 11:55 2025/4/15
    * @Param
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> commonRuleListInfo() {
        HashMap<String, Object> res = new HashMap<>();
        // 获取当前的流控规则
        List<FlowRule> flowRules = FlowRuleManager.getRules();
        res.put("flowRule", flowRules);
        // 获取当前熔断规则
        List<DegradeRule> blowRules = DegradeRuleManager.getRules();
        res.put("blowRule", blowRules);
        // 获取当前热点规则
        List<ParamFlowRule> hotRules = ParamFlowRuleManager.getRules();
        res.put("hotRule", hotRules);
        // 获取当前系统规则
        List<SystemRule> systemRules = SystemRuleManager.getRules();
        res.put("systemRule", systemRules);
        return CommonResult.success(res);
    }

    /**
    * @Author GroundDemo
    * @Description 修改流控规则
    * @Date 13:44 2025/4/15
    * @Param [ruleDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> flowRuleUpdate(YwuFlowRuleDto ruleDto) {
        // 先删除数据
        deleteFlowRules(ruleDto);
        // 再添加数据
        loadFlowRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 修改熔断规则
    * @Date 13:46 2025/4/15
    * @Param [ruleDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> blowRuleUpdate(YwuBlowRuleDto ruleDto) {
        // 先删除数据
        deleteBlowRules(ruleDto);
        // 再添加数据
        loadDegradeRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 修改热点规则
    * @Date 13:47 2025/4/15
    * @Param [ruleDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> hotRuleUpdate(YwuHotRuleDto ruleDto) {
        // 先删除数据
        deleteHotRules(ruleDto);
        // 再添加数据
        loadHotRules(ruleDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 修改系统规则
    * @Date 13:47 2025/4/15
    * @Param [ruleDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> systemRuleUpdate(YwuSystemRuleDto ruleDto) {
        // 先删除数据
        deleteSystemRules(ruleDto);
        // 再添加数据
        loadSystemRules(ruleDto);
        return CommonResult.success(null);
    }
}
